﻿using pandx.Mulan.Settings.Dto;
using pandx.Mulan.Settings.Host.Dto;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Authorization;
using Abp.Net.Mail;
using Abp.Runtime.Security;
using Abp.Zero.Configuration;
using pandx.Mulan.Authorization;
using pandx.Mulan.Configuration;

namespace pandx.Mulan.Settings.Host
{
    public class HostSettingsAppService : SettingsAppServiceBase,IHostSettingsAppService
    {
        public HostSettingsAppService(IEmailSender emailSender,IAppConfigurationAccessor configurationAccessor) : base(emailSender,configurationAccessor)
        {
        }

        #region Get Settings

        [AbpAuthorize(AppPermissions.Pages_Administration_Settings_Browse)]
        public async Task<HostSettingsEditDto> GetAllSettings()
        {
            return new HostSettingsEditDto
            {
                Email=await GetEmailSettingsAsync(),
                Security = await GetSecuritySettingsAsync(),
                
                PeriodicBackgroundWorker = await GetPeriodicBackgroundWorkerSettingsAsync()
            };
        }

        private async Task<PeriodicBackgroundWorkerSettingsEditDto> GetPeriodicBackgroundWorkerSettingsAsync()
        {
            return new PeriodicBackgroundWorkerSettingsEditDto
            {
                ExpireAuditLogDelete = Convert.ToInt32(await SettingManager.GetSettingValueAsync(AppSettings.PeriodicBackgroundWorker.ExpireAuditLogDelete))
            };
        }

        private async Task<SecuritySettingsEditDto> GetSecuritySettingsAsync()
        {
            return new SecuritySettingsEditDto
            {
                UserDefaultPasswordComplexitySettings = false,
                UserLockout = await GetUserLockoutSettingsAsync(),
                AllowOneConcurrentLoginPerUser = await GetOneConcurrentLoginPerUserSettingsAsync()
            };
        }

        private async Task<bool> GetOneConcurrentLoginPerUserSettingsAsync()
        {
            return Convert.ToBoolean(
                await SettingManager.GetSettingValueAsync(AppSettings.Security.AllowOneConcurrentLoginPerUser));

        }

        private async Task<UserLockoutSettingsEditDto> GetUserLockoutSettingsAsync()
        {
            return new UserLockoutSettingsEditDto
            {
                IsEnabled =Convert.ToBoolean(await SettingManager.GetSettingValueAsync(AbpZeroSettingNames.UserManagement.UserLockOut.IsEnabled)),
                MaxFailedAccessAttemptsBeforeLockout = Convert.ToInt32(await SettingManager.GetSettingValueAsync(AbpZeroSettingNames.UserManagement.UserLockOut.MaxFailedAccessAttemptsBeforeLockout)),
                DefaultAccountLockoutSeconds = Convert.ToInt32(await SettingManager.GetSettingValueAsync(AbpZeroSettingNames.UserManagement.UserLockOut.DefaultAccountLockoutSeconds))
            };

        }

        private async Task<EmailSettingsEditDto> GetEmailSettingsAsync()
        {
            var smtpPassword = await SettingManager.GetSettingValueAsync(EmailSettingNames.Smtp.Password);

            return new EmailSettingsEditDto
            {
                DefaultFromAddress = await SettingManager.GetSettingValueAsync(EmailSettingNames.DefaultFromAddress),
                DefaultFromDisplayName =
                    await SettingManager.GetSettingValueAsync(EmailSettingNames.DefaultFromDisplayName),
                SmtpHost = await SettingManager.GetSettingValueAsync(EmailSettingNames.Smtp.Host),
                SmtpPort = Convert.ToInt32(await SettingManager.GetSettingValueAsync(EmailSettingNames.Smtp.Port)),
                SmtpUserName = await SettingManager.GetSettingValueAsync(EmailSettingNames.Smtp.UserName),
                SmtpPassword = SimpleStringCipher.Instance.Decrypt(smtpPassword),
                SmtpDomain = await SettingManager.GetSettingValueAsync(EmailSettingNames.Smtp.Domain),
                SmtpEnableSsl = Convert.ToBoolean(await SettingManager.GetSettingValueAsync(EmailSettingNames.Smtp.EnableSsl)),
                SmtpUseDefaultCredentials =
                    Convert.ToBoolean(await SettingManager.GetSettingValueAsync(EmailSettingNames.Smtp.UseDefaultCredentials)),
            };
        }
        #endregion

        #region Update Settings
        [AbpAuthorize(AppPermissions.Pages_Administration_Settings_Save)]
        public async Task UpdateAllSettings(HostSettingsEditDto input)
        {
            await UpdateEmailSettingsAsync(input.Email);
            await UpdateSecuritySettingsAsync(input.Security);
            await UpdatePeriodicBackgroundWorkerSettingsAsync(input.PeriodicBackgroundWorker);
        }

        private async Task UpdatePeriodicBackgroundWorkerSettingsAsync(PeriodicBackgroundWorkerSettingsEditDto input)
        {
            await SettingManager.ChangeSettingForApplicationAsync(
                AppSettings.PeriodicBackgroundWorker.ExpireAuditLogDelete, input.ExpireAuditLogDelete.ToString());

        }

        private async Task UpdateSecuritySettingsAsync(SecuritySettingsEditDto input)
        {
            await UpdateUserLockOutSettingsAsync(input.UserLockout);
            await UpdateOneConcurrentLoginPerUserSettingAsync(input.AllowOneConcurrentLoginPerUser);
            
        }

        private async Task UpdateOneConcurrentLoginPerUserSettingAsync(bool input)
        {
            await SettingManager.ChangeSettingForApplicationAsync(
                AppSettings.Security.AllowOneConcurrentLoginPerUser, input.ToString().ToLowerInvariant());
            
        }

        private async Task UpdateUserLockOutSettingsAsync(UserLockoutSettingsEditDto input)
        {
            await SettingManager.ChangeSettingForApplicationAsync(
                AbpZeroSettingNames.UserManagement.UserLockOut.IsEnabled,
                input.IsEnabled.ToString().ToLowerInvariant());
            await SettingManager.ChangeSettingForApplicationAsync(
                AbpZeroSettingNames.UserManagement.UserLockOut.DefaultAccountLockoutSeconds,
                input.DefaultAccountLockoutSeconds.ToString());
            await SettingManager.ChangeSettingForApplicationAsync(
                AbpZeroSettingNames.UserManagement.UserLockOut.MaxFailedAccessAttemptsBeforeLockout,
                input.MaxFailedAccessAttemptsBeforeLockout.ToString());
            
        }

        public async Task UpdateEmailSettingsAsync(EmailSettingsEditDto input)
        {
            await this.SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.DefaultFromAddress,
                input.DefaultFromAddress);
            await this.SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.DefaultFromDisplayName,
                input.DefaultFromDisplayName);
            await this.SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.Host, input.SmtpHost);
            await this.SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.Port, input.SmtpPort.ToString(CultureInfo.InvariantCulture));
            await this.SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.UserName,
                input.SmtpUserName);
            await this.SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.Password,
                SimpleStringCipher.Instance.Encrypt(input.SmtpPassword));
            await this.SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.Domain, input.SmtpDomain);
            await this.SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.EnableSsl,
                input.SmtpEnableSsl.ToString().ToLowerInvariant());
            await this.SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.UseDefaultCredentials,
                input.SmtpUseDefaultCredentials.ToString().ToLowerInvariant());
        }
        #endregion


    }
}

